package bean;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;

import bean.vo.CondicionPagoVO;
import bean.vo.CotizacionVO;
import bean.vo.ItemCotizacionVO;

@Entity 
@Table( name = "cotizaciones" )
@SuppressWarnings({"unchecked"})
public class Cotizacion extends EntidadPersistente {
	private Integer numeroCotizacion;
	@OneToOne ( cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH} )
	@Cascade( org.hibernate.annotations.CascadeType.SAVE_UPDATE)
	private SolicitudCotizacion solicitudCotizacion;
	private Date fechaEmision;
	private Date fechaCaducidad;
	private Float porcentajeDescuentoEfectivo;
	@OneToMany( cascade = CascadeType.ALL , mappedBy = "cotizacion")
	private List<ItemCotizacion> itemsCotizacion;
	@ManyToMany( cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH} )
	@Cascade( org.hibernate.annotations.CascadeType.SAVE_UPDATE)
	private List<CondicionPago> condicionesPago;
	@ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH} )
	@Cascade( org.hibernate.annotations.CascadeType.SAVE_UPDATE)
	private Cliente cliente;
	
	public Cotizacion () {
		this.itemsCotizacion = new ArrayList<ItemCotizacion>();
		this.condicionesPago = new ArrayList<CondicionPago>();
	}
	
	public Cotizacion (Integer numeroCotizacion, Cliente cliente){
		this();
		this.numeroCotizacion = numeroCotizacion;
		this.cliente = cliente;
	}
	
	public Cotizacion (Integer numeroCotizacion, SolicitudCotizacion solicitudCotizacion,  Date fechaEmision, Date fechaCaducidad){
		this(numeroCotizacion, solicitudCotizacion.getCliente());
		this.solicitudCotizacion = solicitudCotizacion;
		this.fechaEmision = fechaEmision;
		this.fechaCaducidad = fechaCaducidad;
	}
	
	public CotizacionVO getVO() {
		CotizacionVO vo = new CotizacionVO();
		vo.setNumeroCotizacion(numeroCotizacion);
		vo.setNumeroSolicitud(solicitudCotizacion != null ? solicitudCotizacion.getNumeroSolicitud() : null);
		vo.setFechaEmision(fechaEmision);
		vo.setFechaCaducidad(fechaCaducidad);
		vo.setPorcentajeDescuentoEfectivo(porcentajeDescuentoEfectivo);
		vo.setItemsCotizacion(new VOList<ItemCotizacionVO>().getVoList(itemsCotizacion));
		vo.setCondicionesPago(new VOList<CondicionPagoVO>().getVoList(condicionesPago));
		vo.setPorcentajeDescuentoEfectivo(porcentajeDescuentoEfectivo);
		vo.setCliente(cliente != null ? cliente.getVO() : null);
		vo.setFechaSolicitud(solicitudCotizacion.getFechaRecepcion());
		
		return vo;
	}
	
	public Cliente getCliente() {
		return cliente;
	}

	public void setCliente(Cliente cliente) {
		this.cliente = cliente;
	}	
	
	public Integer getNumeroCotizacion() {
		return numeroCotizacion;
	}
	
	public void setNumeroCotizacion(Integer numeroCotizacion) {
		this.numeroCotizacion = numeroCotizacion;
	}
	
	public SolicitudCotizacion getSolicitudCotizacion() {
		return solicitudCotizacion;
	}
	
	public void setSolicitudCotizacion(SolicitudCotizacion solicitudCotizacion) {
		this.solicitudCotizacion = solicitudCotizacion;
	}
	
	public Date getFechaEmision() {
		return fechaEmision;
	}
	
	public void setFechaEmision(Date fechaEmision) {
		this.fechaEmision = fechaEmision;
	}
	
	public Date getFechaCaducidad() {
		return fechaCaducidad;
	}
	
	public void setFechaCaducidad(Date fechaCaducidad) {
		this.fechaCaducidad = fechaCaducidad;
	}
	
	public Float getPorcentajeDescuentoEfectivo() {
		return porcentajeDescuentoEfectivo;
	}
	
	public void setPorcentajeDescuentoEfectivo(Float porcentajeDescuentoEfectivo) {
		this.porcentajeDescuentoEfectivo = porcentajeDescuentoEfectivo;
	}
	
	public List<ItemCotizacion> getItemsCotizacion() {
		return itemsCotizacion;
	}
	
	public void setItemsCotizacion(List<ItemCotizacion> itemsCotizacion) {
		this.itemsCotizacion = itemsCotizacion;
	}
	
	public List<CondicionPago> getCondicionesPago() {
		return condicionesPago;
	}
	
	public void setCondicionesPago(List<CondicionPago> condicionesPago) {
		this.condicionesPago = condicionesPago;
	}
	
	public ItemCotizacion getItemCotizacion(Producto producto) {
		ItemCotizacion val = new ItemCotizacion(this, producto);
		for (ItemCotizacion item : itemsCotizacion) {
			if(item.equals(val))
				return item;
		}
		
		return null;
	}
	
	public void agregarCondicionPago(CondicionPago cp) {
		if (!condicionesPago.contains(cp)) {
			condicionesPago.add(cp);
		}
	}
	
	public void agregarItem(Producto producto, int cantidad, float precio, DescuentoPorCantidad descuento, Proveedor proveedor)
	{
		ItemCotizacion item = new ItemCotizacion(this, producto, cantidad, precio, descuento, proveedor);
		
		if (!itemsCotizacion.contains(item))
		{
			itemsCotizacion.add(item);
		}
	}
	
	public void eliminarItem(Producto producto)
	{
		ItemCotizacion item = new ItemCotizacion(this, producto, 0, 0, null, null);
		
		if (itemsCotizacion.contains(item))
		{
			itemsCotizacion.remove(item);
		}
	}
	
	@Override
	public int hashCode() {
		final int primo = 31;
		int result = 1;
		result = primo * (result + (numeroCotizacion == null ? 0 : numeroCotizacion.hashCode()) 
				+ (cliente == null ? 0 : cliente.hashCode()) );
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) return true;	
		if ((obj == null) || (!(obj instanceof Cotizacion))) {
			return false;
		}
		
		Cotizacion otro = (Cotizacion) obj;
		
		boolean mismoCliente = (cliente!=null && otro.cliente != null ? (cliente.equals(otro.cliente)) : false);
		boolean mismoNumero = (numeroCotizacion!=null && otro.numeroCotizacion != null ? (numeroCotizacion.equals(otro.numeroCotizacion)) : false);
		
		return mismoCliente && mismoNumero;
	}
}
